// const defaultOption = {
// 	duration: 300,
// 	timingFunction: 'linear',
// 	delay: 0,
// 	transformOrigin: '50% 50% 0'
// }
// #ifdef APP-NVUE
const nvueAnimation = uni.requireNativePlugin('animation')

// #endif
class MPAnimation {
    constructor(options, _this) {
        this.options = options
        this.animation = uni.createAnimation(options)
        this.currentStepAnimates = {}
        this.next = 0
        this.$ = _this

    }

    _nvuePushAnimates(type, args) {
        let aniObj = this.currentStepAnimates[this.next]
        let styles = {}
        if (!aniObj) {
            styles = {
                styles: {},
                config: {}
            }
        } else {
            styles = aniObj
        }
        if (animateTypes1.includes(type)) {
            if (!styles.styles.transform) {
                styles.styles.transform = ''
            }
            let unit = ''
            if (type === 'rotate') {
                unit = 'deg'
            }
            styles.styles.transform += `${type}(${args + unit}) `
        } else {
            styles.styles[type] = `${args}`
        }
        this.currentStepAnimates[this.next] = styles
    }

    _animateRun(styles = {}, config = {}) {
        let ref = this.$.$refs['ani'].ref
        if (!ref) return
        return new Promise((resolve, reject) => {
            nvueAnimation.transition(ref, {
                styles,
                ...config
            }, res => {
                resolve()
            })
        })
    }

    _nvueNextAnimate(animates, step = 0, fn) {
        let obj = animates[step]
        if (obj) {
            let {
                styles,
                config
            } = obj
            this._animateRun(styles, config).then(() => {
                step += 1
                this._nvueNextAnimate(animates, step, fn)
            })
        } else {
            this.currentStepAnimates = {}
            typeof fn === 'function' && fn()
            this.isEnd = true
        }
    }

    step(config = {}) {
        // #ifndef APP-NVUE
        this.animation.step(config)
        // #endif
        // #ifdef APP-NVUE
        this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
        this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
        this.next++
        // #endif
        return this
    }

    run(fn) {
        // #ifndef APP-NVUE
        this.$.animationData = this.animation.export()
        this.$.timer = setTimeout(() => {
            typeof fn === 'function' && fn()
        }, this.$.durationTime)
        // #endif
        // #ifdef APP-NVUE
        this.isEnd = false
        let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
        if (!ref) return
        this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
        this.next = 0
        // #endif
    }
}


const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
    'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
    'translateZ'
]
const animateTypes2 = ['opacity', 'backgroundColor']
const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
    MPAnimation.prototype[type] = function (...args) {
        // #ifndef APP-NVUE
        this.animation[type](...args)
        // #endif
        // #ifdef APP-NVUE
        this._nvuePushAnimates(type, args)
        // #endif
        return this
    }
})

export function createAnimation(option, _this) {
    if (!_this) return
    clearTimeout(_this.timer)
    return new MPAnimation(option, _this)
}
